package com.bbk.security.realm;

import java.util.Collection;
import java.util.List;
import java.util.Set;
 
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.CacheManagerAware;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
 
import com.bbk.bean.Module;
import com.bbk.bean.Role;
import com.bbk.bean.User;
import com.bbk.bean.enums.EnumStatus;
import com.bbk.common.Constants;
import com.bbk.common.ObjectUtils;
import com.bbk.common.exception.UserInputException;
import com.bbk.security.cache.RedisCache;
import com.bbk.service.IBaseService;
import com.bbk.service.IModuleService;
import com.bbk.service.IRoleService;
import com.bbk.service.IUserService;
 
import fmath.a.a.c;
 
public class CustomRealm extends AuthorizingRealm implements Realm, InitializingBean {
 
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IModuleService moduleService;
    @Autowired
    private IUserService userService;
 
    @Autowired
    private RedisCache<String, Object> redisCache;
 
    @Autowired
    private IBaseService baseService;
 
    private Logger logger = Logger.getLogger(this.getClass());
 
    public CustomRealm() {
    }
 
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //logger.info("授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        String username = (String) super.getAvailablePrincipal(principals);
        User user = userService.findUserByUsername(username);
        List<Role> roles = roleService.queryRolesByUserId(user);
 
        StringBuilder sb = new StringBuilder();
        for (Role role : roles) {
            info.addRole(role.getCode());
            sb.append(role.getId());
            sb.append(",");
        }
        if (sb.length() > 0) {
            List<Module> perms = moduleService.findPermNamesByUser(sb.substring(0, sb.length() - 1));
            for (Module module : perms) {
                if (ObjectUtils.isNotEmpty(module.getCode())) {
                    info.addStringPermission(module.getCode());
                }
            }
            redisCache.put(Constants.getUserModuleCacheKey(user.getUserName()), perms);
        }
        //cacheManager.getCache("").clear();
        redisCache.put(Constants.getUserRolesCacheKey(user.getUserName()), roles);
        return info;
    }
 
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
 
        SimpleAuthenticationInfo info = null;
 
        UsernamePasswordToken upt = (UsernamePasswordToken) token;
        User user = userService.findUserByUsername(upt.getUsername());
        if (user == null) {
            throw new AuthenticationException("用户名不存在！");
        }
        if (user.getStatus() < EnumStatus.NORMAL.getStatus()) {
            throw new UserInputException("您的帐号号已被限制登录，如需帮助请联系管理员！");
        }
        redisCache.put(Constants.getUserSessionKey(user.getUserName()), user);
        info = new SimpleAuthenticationInfo(user.getUserName(), user.getUserPsw(), getName());
        return info;
    }
 
    /**
     * 更新用户授权信息缓存.
     */
    public void clearCachedAuthorizationInfo(String principal) {
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
        super.clearCachedAuthorizationInfo(principals);
        super.clearCache(principals);
        super.clearCachedAuthenticationInfo(principals);
        redisCache.remove(Constants.getUserModuleCacheKey(principal));
        redisCache.remove(Constants.getUserRolesCacheKey(principal));
    }
 
    /**
     * 清除所有用户授权信息缓存.
     */
    public void clearAllCachedAuthorizationInfo() {
        redisCache.clear();
        /*Cache<Object, AuthenticationInfo> cache = getAuthenticationCache();
        if (null != cache) {
            for (Object key : cache.keys()) {
                cache.remove(key);
            }
        }*/
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
    }
 
}
